<template>
  <div>
    <el-form label-width="80px" :model="spuInfo">
      <el-form-item label="SPU名称">
        <el-input v-model="spuInfo.spuName" placeholder="SPU名称" />
      </el-form-item>
      <el-form-item label="品牌">
        <!-- spuInfo.tmId 指的是我点击修改按钮当前行的row的商品id -->
        <el-select v-model="spuInfo.tmId" placeholder="请选择品牌">
          <!-- :value="item.id" 收集option选项内的id -->
          <el-option v-for="item in trademarkList" :key="item.id" :label="item.tmName" :value="item.id" />
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述"> <el-input v-model="spuInfo.description" placeholder="SPU描述" type="textarea" rows="4/" /></el-form-item>
      <el-form-item label="SPU名称">
        <!-- action 上传的地址
            list-type : 该upload的类型:照片墙
            file-list: 预览图片的数组需要name和url2个字段硬性要求
        -->
        <el-upload action="dev-api/admin/product/fileUpload" list-type="picture-card" :file-list="spuImageList" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleSuccess">
          <i class="el-icon-plus" />
        </el-upload>
        <el-dialog :visible.sync="dialogVisible">
          <img width="100%" :src="dialogImageUrl" />
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性">
        <el-select v-model="attrIdAndName" :placeholder="unSelectSaleAttr.length > 0 ? `还有${unSelectSaleAttr.length}未选择` : '没有可选值啦~'">
          <!-- 这里引用的是计算出来的剩余可选平台属性值的id,name -->
          <el-option v-for="item in unSelectSaleAttr" :key="item.id" :label="item.name" :value="`${item.id}:${item.name}`" />
        </el-select>
        <el-button class="addshowattr" :disabled="!attrIdAndName" type="primary" icon="el-icon-plus" @click="addspuSaleAttrList">添加显示属性</el-button>
      </el-form-item>
      <el-form-item>
        <el-table style="width: 100%" label-width="80px" border :data="spuInfo.spuSaleAttrList">
          <el-table-column type="index" label="序号" width="80" align="center" />
          <el-table-column prop="saleAttrName" width="80" label="属性名" align="center" />
          <el-table-column label="属性值名称列表" align="center">
            <template slot-scope="{ row, $index }">
              <!-- tag组件的使用,该组件和attr组件下的 span展示模式 与 input编辑模式 原理一样 -->
              <el-tag v-for="(tag, i) in row.spuSaleAttrValueList" :key="tag.id" closable :disable-transitions="false" @close="handleClose(row, i)">
                {{ tag.saleAttrValueName }}
              </el-tag>
              <!-- 编辑模式  inputVisible 控制显示与隐藏-->
              <el-input v-if="row.inputVisible" ref="saveTagInput" v-model="row.inputValue" class="input-new-tag" size="small" width="80" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)" />
              <!-- 展示模式 -->
              <el-button v-else class="button-new-tag" size="small" @click="showInput(row)">+ New Tag</el-button>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" width="80">
            <template slot-scope="{ row, $index }">
              <el-button icon="el-icon-delete" size="mini" type="danger" @click="removeAttrRow(row, $index)" />
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="addOrUpdateSpuInfo">保存</el-button>
        <el-button class="addshowattr" @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: '',
  data() {
    return {
      dialogImageUrl: '',
      // 照片墙的 Dialog
      dialogVisible: false,
      // spu对象信息
      spuInfo: {
        // spu名称
        spuName: '',
        // 描述
        description: '',
        // 三级分类的id
        category3Id: 0,
        // 品牌的id收集
        tmId: '',
        // 平台属性名称与属性值
        spuSaleAttrList: [],
        // 收集spu图片的信息
        spuImageList: [],
      },
      // 品牌信息下拉框内的数据
      trademarkList: [],
      // sku 信息图片
      spuImageList: [],
      // 获取平台全部销售属性
      baseSaleAttrList: [],
      // 品牌全部属性的剩余可选(临时存储地方,存的是options里面的id)
      attrIdAndName: '',
    }
  },
  computed: {
    // 动态计算出目前spu剩余可选商品属性(版本、尺寸、颜色)
    unSelectSaleAttr() {
      return this.baseSaleAttrList.filter((item) => {
        return this.spuInfo.spuSaleAttrList.every((x) => {
          return x.saleAttrName !== item.name
        })
      })
    },
  },
  methods: {
    // upload照片墙删除的回调事件
    handleRemove(file, fileList) {
      // file : 被删除的那项
      // fileList : 删除后所剩余的图片数组
      console.log(file, fileList)
      // 临时存储(因为需要去除多余的参数:name,url,才能存到 skuInfo对象里面)
      this.spuImageList = fileList
    },
    // upload照片墙预览的回调事件
    handlePictureCardPreview(file) {
      // 当前预览的图片 url 地址,为当前已上传的图片url
      this.dialogImageUrl = file.url
      // 把照片墙的 Dialog 展示出来
      this.dialogVisible = true
    },
    // upload照片墙上传成功的回调事件
    handleSuccess(response, file, fileList) {
      // response 上传成功后返回存储成功的服务器地址
      // file 该张图片上传成功后返回存储成功的服务器地址
      // fileList 最新的照片墙数组数据(和删除的回调fileList性质一样)
      console.log(response, file, fileList)
      // 临时存储(因为需要去除多余的参数:name,url,才能存到 skuInfo对象里面)
      this.spuImageList = fileList
    },
    // 初始化修改对象的信息(发送4个请求)
    async initSpuData(row) {
      // 获取 spu 信息接口
      const spuInfores = await this.$api.spu.reqSpu(row.id)
      if (spuInfores.code === 200) {
        this.spuInfo = spuInfores.data
        console.log(spuInfores, 'spuInfores')
      }
      // 获取品牌的信息
      const trademarkListres = await this.$api.spu.reqTradeMarkList()
      if (trademarkListres.code === 200) {
        this.trademarkList = trademarkListres.data
        console.log(trademarkListres, 'trademarkList')
      }
      // 获取spu图片信息的接口
      const spuImageListres = await this.$api.spu.reqSpuImageList(row.id)
      if (spuImageListres.code === 200) {
        const res = spuImageListres.data
        // 由于照片墙显示图片的数据需要数组,数组里面的元素需要有 name 与 url 字段
        // 需要把服务器返回的数据进行修改(赋值前增加这二个字段)
        res.forEach((item) => {
          item.name = item.imgName
          item.url = item.imgUrl
        })
        this.spuImageList = res
        console.log(spuImageListres, 'spuImageListres')
      }
      // 获取平台全部销售属性---整个平台销售属性一共三个(为什么最多三个?后端设置的?)
      const baseSaleAttrListres = await this.$api.spu.reqBaseSaleAttrList()
      if (baseSaleAttrListres.code === 200) {
        this.baseSaleAttrList = baseSaleAttrListres.data
        console.log(baseSaleAttrListres, 'baseSaleAttrListres')
      }
    },
    // 增添平台属性的名字与id的回调事件
    addspuSaleAttrList() {
      // 结构赋值 id , 平台属性名字
      const [baseSaleAttrId, saleAttrName] = this.attrIdAndName.split(':')
      this.spuInfo.spuSaleAttrList.push({
        // 平台三大属性的id
        baseSaleAttrId: baseSaleAttrId,
        // 平台三大属性的名字
        saleAttrName: saleAttrName,
        // 平台三大属性名字的属性值
        spuSaleAttrValueList: [],
      })
      // 清空数据
      this.attrIdAndName = ''
    },
    // 关闭 tag 标签事件
    handleClose(row, index) {
      console.log(row, index)
      row.spuSaleAttrValueList.splice(index, 1)
    },
    // 删除一整行销售属性 row 回调事件
    removeAttrRow(row, index) {
      console.log(row, index)
      this.spuInfo.spuSaleAttrList.splice(index, 1)
    },
    // tag标签离开事件(收集数据和展示数据)
    handleInputConfirm(row) {
      console.log(row)
      // 判断当前 row 收集的数据是否为空
      if (row.inputValue.trim() === '') {
        this.$message('不能为空哦')
        row.inputVisible = false
        return
      }
      // 判断当前 row 收集的数据是否为重复
      const replaceRes = row.spuSaleAttrValueList.every((item) => item.saleAttrValueName.trim() !== row.inputValue.trim())
      console.log(replaceRes)
      // 真即为不重复,假即为重复了
      if (!replaceRes) return this.$message('不能重复哦')
      // 变为展示模式
      row.inputVisible = false
      // 执行添加到展示数据的数组里面(完成展示/收集数据功能)
      row.spuSaleAttrValueList.push({
        // 添加时需要的字段,3大属性之1的id,用户的属性值
        baseSaleAttrId: row.baseSaleAttrId,
        saleAttrValueName: row.inputValue,
      })
    },
    // 点击添加 tag 按钮的回调事件(收集数据和展示数据)
    showInput(row) {
      // row.inputVisible = true  并非响应式
      // 动态添加响应式数据,保存用户填写的tag属性值
      this.$set(row, 'inputValue', '')
      // 动态添加响应式数据,供编辑模式/展示模式使用(不能写在data里,应该为每一行row单独分配,单独控制编辑模式与展示模式)
      // inputVisible控制button与input的显示与隐藏
      this.$set(row, 'inputVisible', true)
      // 自动获取焦点
      this.$nextTick(() => {
        this.$refs.saveTagInput.focus()
      })
    },
    // 修改 or 新增 spu 事件回调
    async addOrUpdateSpuInfo() {
      this.spuInfo.spuImageList = this.spuImageList.map((item) => {
        // 针对新上传的图片还是服务器返回的图片都执行添加该2字段操作
        return {
          imgName: item.name,
          // 判断是服务器返回的图片则采取后面做法,新上传图片则采取前面做法
          imgUrl: (item.response && item.response.data) || item.url,
        }
      })
      // 发修改请求
      const res = await this.$api.spu.reqAddOrUpdateSpu(this.spuInfo)
      console.log(res)
      if (res.code === 200) {
        this.$message({ type: 'success', message: '修改成功' })
        // 触发自定义事件,让页面从修改spu面板转换为spu展示面板(并且告诫该次保存是修改还是新增)
        this.$emit('changeScene', { scene: 0, flag: this.spuInfo.id ? '修改' : '新增' })
      }
      // 清除数据
      Object.assign(this._data, this.$options.data())
    },
    // 新增 spu 发送的2个请求
    async addSpuData(category3Id) {
      console.log(category3Id)
      this.spuInfo.category3Id = category3Id
      // 获取品牌的信息
      const trademarkListres = await this.$api.spu.reqTradeMarkList()
      if (trademarkListres.code === 200) {
        this.trademarkList = trademarkListres.data
        console.log(trademarkListres, 'trademarkList')
      }
      // 获取平台全部销售属性---整个平台销售属性一共三个(为什么最多三个?后端设置的?)
      const baseSaleAttrListres = await this.$api.spu.reqBaseSaleAttrList()
      if (baseSaleAttrListres.code === 200) {
        this.baseSaleAttrList = baseSaleAttrListres.data
        console.log(baseSaleAttrListres, 'baseSaleAttrListres')
      }
    },
    // 点击取消的事件回调
    cancel() {
      this.$emit('changeScene', { scene: 0, flag: '' })
      // 清理数据
      // Object.asign : es6中新增的方法可以合并对象
      // 组件实例 this._data,可以操作 data 中的响应式数据
      // console.log(this._data) this._data // 当前组件的data(当前组件data的状态,已经赋值or未赋值,看不懂看 p 164)
      // console.log(this.$options) // 当前组件的data(一开始未赋值的状态,初始化起始状态)
      Object.assign(this._data, this.$options.data())
    },
  },
}
</script>

<style>
.addshowattr {
  margin-left: 20px;
}
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>
